#ifndef CIPHER_H
#define CIPHER_H

#include <QObject>

class Cipher : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QByteArray alphabet   READ alphabet   WRITE setAlphabet   NOTIFY alphabetChanged)
    Q_PROPERTY(QByteArray plainText  READ plainText  WRITE setPlainText  NOTIFY plainTextChanged)
    Q_PROPERTY(QByteArray cipherText READ cipherText WRITE setCipherText NOTIFY cipherTextChanged)
    Q_PROPERTY(QByteArray defaultKey READ defaultKey WRITE setDefaultKey NOTIFY defaultKeyChanged)

public:
    enum CipherAlgorithm {
        Undefined = -1,
        Caesar,
        Vigenere,
        Autokey,
        XORVigenere,
        XORAutokey
    };

    Cipher(QByteArray alphabet = QByteArray(), QByteArray defaultKey = QByteArray(), CipherAlgorithm algorithm = Undefined, QObject *parent = 0);

    Q_INVOKABLE inline QByteArray defaultKey() {return _defaultKey;}
    Q_INVOKABLE inline QByteArray alphabet  () {return _alphabet  ;}
    Q_INVOKABLE inline QByteArray plainText () {return _plainText ;}
    Q_INVOKABLE inline QByteArray cipherText() {return _cipherText;}

    static QByteArray encrypt(CipherAlgorithm algorithm, QByteArray alphabet, QByteArray plaintext , QByteArray key);
    static QByteArray decrypt(CipherAlgorithm algorithm, QByteArray alphabet, QByteArray ciphertext, QByteArray key);


signals:
    void   alphabetChanged();
    void  plainTextChanged();
    void cipherTextChanged();
    void defaultKeyChanged();
    
public slots:
    void setAlphabet  (QByteArray alphabet);
    void setPlainText (QByteArray plainText);
    void setCipherText(QByteArray cipherText);
    void setDefaultKey(QByteArray key);

    void encrypt(QByteArray key = QByteArray(), CipherAlgorithm algorithm = Undefined);
    void decrypt(QByteArray key = QByteArray(), CipherAlgorithm algorithm = Undefined);

    void setAsciiMode();
    void setBinaryMode();
    
private:
    CipherAlgorithm _algorithm;
    QByteArray _defaultKey;
    QByteArray _alphabet;
    QByteArray _plainText;
    QByteArray _cipherText;

    QByteArray vigenere(QByteArray plain, QByteArray key, bool decrypt, bool doXor = false);
    QByteArray autokey (QByteArray plain, QByteArray key, bool decrypt, bool doXor = false);
    bool setupKey(QByteArray in, int *out, bool decrypt);

};

#endif // CIPHER_H
